<!--
 * @Description  :
 * @Version      : 1.0
 * @Author       : seraph
 * @Date         : 2024-12-13 16:10:18
 * @LastEditors  : seraph
 * @LastEditTime : 2024-12-24 12:28:05
-->
<template>
  <h2>指令 Directives</h2>
  <h4>指令是带有 v- 前缀的特殊 attribute。v-bind 可以简写为 :，v-on 可以简写为 @。</h4>
  <h4>指令 attribute 的期望值为一个 JavaScript 表达式 (除了 v-for、v-on 和 v-slot)。</h4>
  <h4> 除了 v-for、v-on 和 v-slot, 它们的 attribute 值不是 JavaScript 表达式，而是一段指令表达式。</h4>
  <h4>一个指令的任务是在其表达式的值变化时响应式地更新 DOM。</h4>
  <hr />

  <h4>示例代码：&lt;span v-if="seen"&gt;Now you see me&lt;/span&gt;</h4>
  <h4>后面的内容是否可见？
    <span v-if="seen">Now you see me</span>
  </h4>
  <button @click="seen = !seen">Toggle</button>
  <h4>这里，`v-if` 指令会基于表达式 `seen` 的值的真假来移除/插入该 `&lt;span&gt;` 元素。seen: {{ seen }}</h4>
  <hr />
  <!-- TAG: ======================================================== -->

  <h4>参数 Arguments</h4>
  <h4>指令可以带有参数，参数在指令名称的后面，以冒号 : 分隔。</h4>
  <h4>例如，v-bind 指令可以用于绑定一个 attribute。</h4>
  <h4>示例代码：&lt;a v-bind:href="url"&gt; 链接 &lt;/a&gt;</h4>
  <h4>简写：&lt;a :href="url"&gt; 链接 &lt;/a&gt;</h4>
  <hr />
  <!-- TAG: ======================================================== -->

  <h4>动态参数</h4>
  <h4>指令参数可以是动态的，即根据数据变化而变化。同样在指令参数上也可以使用一个 JavaScript 表达式，需要包含在一对方括号内。</h4>
  <h4>示例代码：&lt;span v-bind:[attributeName]="attributeValue"&gt; 鼠标移到这里有惊喜 &lt;/span&gt;</h4>
  <h4><span v-bind:[attributeName]="attributeValue" title="查看源码会发现属性名称一个是 id 一个是 class"> 鼠标移到这里有惊喜 </span></h4>
  <button @click="handleChange">toggle arguments</button>
  <hr />
  <!--TAG: ======================================================== -->

  <h4></h4>
  <hr />
  <!--TAG: ======================================================== -->



  <h4>以下是 Vue 3 中常用的指令列表：</h4>
  <ul>
    <li>v - bind：动态地绑定一个或多个属性，或一个组件 prop 到表达式。</li>
    <p> 示例代码：</p>
    <p> &lt;im g v-bi nd: src=" imageUrl"&gt; 或 &lt;img :src="imageUrl" &gt;</p>
    <br />

    <li>v-model：在表单控件元素上创建双向数据绑定。</li>
    <p>示例代码：</p>
    <p>&lt;input type="text" v-model="inputValue"&gt;</p>
    <br />

    <li>v-if：条件性地渲染一块内容。</li>
    <p>示例代码：</p>
    <p>&lt;div v-if="isVisible"&gt;现在可见&lt;/div&gt;</p>
    <br />

    <li>v-else-if：v-if 的姊妹指令，用于else-if条件。</li>
    <p>示例代码：</p>
    <p>&lt;div v-if="type === 'A'"&gt;类型是 A&lt;/div&gt; &lt;div v-else-if="type === 'B'"&gt;类型是 B&lt;/div&gt;
      &lt;div
      v-else&gt;类型不是 A 或 B&lt;/div&gt;</p>
    <br />

    <li>v-else：v-if 的姊妹指令，用于else条件</li>
    <p>示例代码：</p>
    <p>&lt;div v-if="type === 'A'"&gt;类型是 A&lt;/div&gt; &lt;div v-else"&gt;类型不是 A &lt;/div&gt;</p>
    <h4>&lt;span v-if="str === 'A'"&gt;是 A&lt;/span&gt;&lt;span v-else-if="str === 'B'"&gt;是
      B&lt;/span&gt;&lt;span
      v-else&gt;不是 A 和 B&lt;/span&gt;</h4>
    <h4><span v-if="str === 'A'">是 A</span><span v-else-if="str === 'B'">是 B</span><span v-else>不是 A 和 B</span>
    </h4>
    <button @click="str = 'A'">A</button>
    <button @click="str = 'B'">B</button>
    <button @click="str = 'C'">C</button>

    <br />
    <br />

    <li>v-show：根据表达式的真假值切换元素的显示。</li>
    <p>示例代码：</p>
    <p>&lt;span v-show="isVisible"&gt;现在可见&lt;/span&gt;</p>
    <p>后面的 span 元素的 id 是 "blue"，所以在显示时，它的颜色是蓝色。
      <span v-show="isVisible" id="blue">现在可见</span>
    </p>
    <button @click="isVisible = !isVisible">toggle show</button>
    <hr />
    <h2>以下这些指令不需要表达式</h2>
    <li>v-once：渲染元素后，不再重新渲染，即使数据变化。【无参数】</li>
    <p>示例代码：</p>
    <p>&lt;span v-once&gt;这个内容不会改变&#123;{ str }&#125;&lt;/span&gt;</p>
    <p><span v-once>这个内容不会改变:{{ str }}</span>。<span>这里是 str 的值：{{ str }}。点击上面（if~else）的按钮，str 的值会改变。</span></p>
    <br />

    <li>v-for：基于源数据多次渲染元素或模板块。【一条完整的 JS 语句】</li>
    <p>示例代码：</p>
    <p>&lt;ul&gt; &lt;li v-for="item in items"&gt;&#123;{ item }&#125;&lt;/li&gt; &lt;/ul&gt;</p>
    <br />

    <li>v-on：监听 DOM 事件，并在事件触发时执行表达式。【事件名或方法名】</li>
    <p>简写形式：@</p>
    <p>示例代码：</p>
    <p>&lt;button v-on:click="greet"&gt;Greet&lt;/button&gt;</p>
    <button v-on:click="greet">Greet</button>
    <br />
    <br />

    <li>v-slot：用于定义插槽内容。【插槽名】</li>
    <p>具体详见 vue3 笔记中的 slot 部分。</p>
  </ul>
  <h4></h4>


</template>

<script lang="ts" setup>
import { ref, reactive, onMounted, watch, computed } from 'vue'
const seen = ref(true);

const str = ref('A');

const isVisible = ref(true);


const greet = () => {
  console.log('Hello, Vue! This is a greeting from Vue.js');
  alert('Hello, Vue! This is a greeting from Vue.js');
}

const msg = ref(''); // 立即更新的数据
const lazyMsg = ref(''); // 失去焦点时更新的数据

watch(msg, (newVal, oldVal) => {
  console.log(Date.now(), '立即更新的数据', newVal, oldVal);
});

watch(lazyMsg, (newVal, oldVal) => {
  console.log(Date.now(), '失去焦点时更新的数据', newVal, oldVal);
});

const age = ref(20);
const ValidAge = ref(20);
watch(age, (newVal, oldVal) => {
  if (!isNaN(newVal)) {
    ValidAge.value = newVal;
  }
  console.log(Date.now(), 'age is valid', newVal, oldVal);
});

const msg1 = ref('');
watch(msg1, (newVal, oldVal) => {
  console.log(Date.now(), 'Input content is', '|' + newVal + '|', oldVal);
});

const attributeName = ref('title');
const attributeValue = ref('Hello Vue!');

const handleChange = () => {
  attributeName.value = attributeName.value === 'id' ? 'class' : 'id';
  attributeValue.value = attributeValue.value === 'blue' ? 'red' : 'blue';
}
</script>

<style scoped>
#blue,
.blue {
  color: blue;
}

#red,
.red {
  color: red;
}

#green {
  color: green;
}

.bold {
  font-weight: bold;
}

/* Chrome, Safari, Edge, Opera */
#numInput[type="number"]::-webkit-outer-spin-button,
#numInput[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* firefox 兼容性 */
#numInput[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}

button {
  margin-right: 10px;
  min-width: 80px;
  font-size: 16px;
  line-height: 150%;
}
</style>
